﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace HY.Utility.Match
{
    public class HtmlElementMatcher
    {
        private HtmlAgilityPack.HtmlDocument _Doc;
        private HtmlAgilityPack.HtmlNode _Root;

        /// <summary>
        /// 选择多个元素
        /// </summary>
        /// <param name="index">第几个元素</param>
        /// <param name="item">内容</param>
        public delegate void SelectNodesEventHandler(int index, List<AttributeValue> item,string outerhtml);

        public HtmlElementMatcher(string html)
        {
            html = System.Web.HttpUtility.HtmlDecode(html);
            _Doc = new HtmlAgilityPack.HtmlDocument();
            _Doc.LoadHtml(html);
            _Root = _Doc.DocumentNode;
        }

        /// <summary>
        /// 获取当前元素的属性值
        /// </summary>
        /// <param name="attribute"></param>
        /// <param name="defaultvalue"></param>
        /// <returns></returns>
        public string GetCurrentNodeAttributeValue(string attribute, string defaultvalue = "")
        {
            if (_Root.Attributes.Contains(attribute))
                return _Root.Attributes[attribute].Value;
            return defaultvalue;
        }

        public string GetCurrentNodeInnerText()
        {
            return _Root.InnerText;
        }

        /// <summary>
        /// 根据XPath获取元素属性值
        /// </summary>
        /// <param name="xpath"></param>
        /// <param name="attribute"></param>
        /// <param name="defaultvalue"></param>
        /// <returns></returns>
        public string GetNodeAttributeValue(string xpath, string attribute, string defaultvalue = "")
        {
            if (string.IsNullOrEmpty(xpath))
            {
                if (_Root.Attributes.Contains(attribute))
                    return _Root.Attributes[attribute].Value;
            }
            else
            {
                var node = _Root.SelectSingleNode(xpath);
                if (node != null)
                    if (node.Attributes.Contains(attribute))
                        return node.Attributes[attribute].Value;
            }
            return defaultvalue;
        }

        /// <summary>
        /// 根据XPath获取多个元素多个属性值
        /// </summary>
        /// <param name="handler"></param>
        /// <param name="xpath"></param>
        /// <param name="defaultvalue"></param>
        /// <param name="attributes"></param>
        public void GetNodesAttributeValues(SelectNodesEventHandler handler, string xpath, string defaultvalue = "", params string[] attributes)
        {
            int i = 0;
            var nodes = _Root.SelectNodes(xpath);
            if (nodes != null)
            {
                foreach (var node in nodes)
                {
                    if (attributes != null)
                    {
                        List<AttributeValue> item = new List<AttributeValue>();
                        if (attributes != null)
                        {
                            foreach (var attribute in attributes)
                            {
                                string value = defaultvalue;
                                if (node.Attributes.Contains(attribute))
                                    value = node.Attributes[attribute].Value;
                                item.Add(new AttributeValue() { Attribute = attribute, Value = value });
                            }
                        }
                        handler?.Invoke(i, item,node.OuterHtml);
                    }
                    ++i;
                }
            }
        }

        public void GetNodesInnerText(SelectNodesEventHandler handler, string xpath)
        {
            int i = 0;
            var nodes = _Root.SelectNodes(xpath);
            if (nodes != null)
            {
                foreach (var node in nodes)
                {
                    var item = new List<AttributeValue>();
                    item.Add(new AttributeValue() { Attribute = "", Value = node.InnerText.Trim() });
                    handler?.Invoke(i, item, node.OuterHtml);
                }
            }
        }

        /// <summary>
        /// 获取元素的内部纯文本
        /// </summary>
        /// <param name="xpath"></param>
        /// <param name="defaultvalue">默认值</param>
        /// <returns></returns>
        public string GetNodeInnerText(string xpath,string defaultvalue="")
        {
            var node = _Root.SelectSingleNode(xpath);
            if (node != null)
                return node.InnerText.Trim();
            return defaultvalue;
        }

        /// <summary>
        /// 获得元素内部HTML
        /// </summary>
        /// <param name="xpath"></param>
        /// <returns></returns>
        public string GetNodeInnerHtml(string xpath)
        {
            var node = _Root.SelectSingleNode(xpath);
            if (node != null)
                return node.InnerHtml.Trim();
            return null;
        }

        public string GetParentNodeOuterHtml(string xpath, int level = 1)
        {
            var node = _Root.SelectSingleNode(xpath);
            if (node != null)
            {
                var top = node;
                for (var i = 0; i < level; ++i)
                {
                    top = top.ParentNode;
                }
                return top.OuterHtml;
            }
            return null;
        }


        /// <summary>
        /// 获得元素的HTML
        /// </summary>
        /// <param name="xpath"></param>
        /// <returns></returns>
        public string GetNodeOuterHtml(string xpath)
        {
            var node = _Root.SelectSingleNode(xpath);
            if (node != null)
                return node.OuterHtml.Trim();
            return null;
        }
    }
}
